
package com.changjiang.luban.utils.file;

import com.aliyun.oss.OSSClient;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.PutObjectResult;
import com.changjiang.luban.utils.GenerateCodeUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 描述:阿里云OSS上传文件工具
 * <p>支持普通文件的上传，限制大小文件上传,限制大小图片上传</p>
 * @author nichangjiang@vip.qq.com
 * 创建时间:2017/12/1. 16:21
 * 修改人:
 * 修改时间:
 * 修改备注:
 * 版本:v1.0
 */
public class AliyunOssUtil {

    private static Logger logger = LoggerFactory.getLogger(AliyunOssUtil.class);

    /** 阿里云API的内或外网域名 */
    private static final String ENDPOINT="http://oss-cn-shanghai.aliyuncs.com";

    /** 阿里云API的密钥Access Key ID */
    private static final String ACCESS_KEY_ID="LTAIuqbkNJdmtB0Y";

    /** 阿里云API的密钥Access Key Secret */
    private static final String ACCESS_KEY_SECRET = "ndDvedE4boNjuoLIfY7SVplIXrdSJC";

    /**存储空间名称*/
    public static final String BUCKET_NAME = "goodsimages";

    /** OSS连接对象 */
    private static OSSClient ossClient = null;

    /** OOS上传的文件名前缀 */
    private static final String FILE_NAME_PREFIX = "F";


    /** 上传返回结果 */
    private static Map<String, Object> resultMap = new HashMap<String, Object>();

    static {
        ossClient = new OSSClient(ENDPOINT,ACCESS_KEY_ID, ACCESS_KEY_SECRET);
    }


    /**
     * 判断bucket是否存在  --Bucket权限:私有
     * @param bucketName bucket名称
     */
    public static void existsBucket(String bucketName){
        try {
            boolean exists = ossClient.doesBucketExist(bucketName);
            if (!exists) {
                logger.info("bucket不存在，新建当前bucket:{}", bucketName);
                ossClient.createBucket(AliyunOssUtil.BUCKET_NAME);
            }
        }catch (Exception e){
            logger.error("创建新Bucket出现异常");
            throw e;
        }

    }

    /**
     * 删除Bucket
     * @param bucketName bucket名称
     * */
    public static final void deleteBucket(String bucketName){
        try{
            ossClient.deleteBucket(bucketName);
            logger.info("bucketName已删除");
        }catch (Exception e){
            logger.error("删除Bucket出现异常");
            throw e;
        }
    }

    /**
     * 上传文件到OSS服务器
     * <note>同名文件会覆盖原文件的内容后保存新的内容到服务器</note>
     * @param file 上传的文件
     * @param bucketName 上传空间名称
     * @param diskName 文件存放的位置标识
     * @return Map<String, Object> map
     * <return_state>true：上传成功  false: 上传失败</return_state>
     * <return_msg>true: 返回文件上传到服务器的路径 false: 文件上传的失败信息反馈</return_msg>
     */
    public static Map<String,Object> uploadFileOSS(MultipartFile file, String bucketName, String diskName){
        //文件输入流
        InputStream uploadInputStrem = null;
        //文件上传的路径
        String uploadPath = "";
        //上传完成返回签名
        String ret = "";
        try{
            String fileName = FILE_NAME_PREFIX+GenerateCodeUtils.getUUId(9);
            existsBucket(bucketName);
            //获取上传文件后缀名
            String fileSuffix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
            //创建上传Object的Metadata
            ObjectMetadata objectMetadata = new ObjectMetadata();
            objectMetadata.setContentLength(file.getSize());
            objectMetadata.setCacheControl("no-cache");
            objectMetadata.setHeader("Pragma", "no-cache");
            objectMetadata.setContentType(fileSuffix);
            objectMetadata.setContentDisposition("inline;filename=" + fileName);
            uploadInputStrem = file.getInputStream();
            uploadPath = diskName + fileName +fileSuffix;
            //上传文件
            logger.debug("正在上传文件到OSS...");
            PutObjectResult putResult = ossClient.putObject(bucketName, uploadPath, uploadInputStrem, objectMetadata);
            logger.debug("上传文件完成...");
            ret = putResult.getETag();
            logger.debug("上传后的文件MD5数字唯一签名:{}",ret);
        }catch (Exception e){
            resultMap.put("state", false);
            resultMap.put("msg", e.getMessage());
            return resultMap;
        }finally {
            try {
                if (uploadInputStrem != null) {
                    uploadInputStrem.close();//关闭文件流
                }

            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        if(!"".equals(ret) && ret!=null){
            resultMap.put("state", true);
            resultMap.put("msg", uploadPath);
            return resultMap;
        }else{
            resultMap.put("state", false);
            resultMap.put("msg", "上传失败!");
            return resultMap;
        }

    }

    /**
     * 上传文件到OSS服务器
     * <note>同名文件会覆盖原文件的内容后保存新的内容到服务器</note>
     * @param file 上传的文件
     * @param bucketName 上传空间名称
     * @param diskName 文件存放的位置标识
     * @param limitSize     上传大小
     * @return Map<String, Object> map
     * <return_state>true：上传成功  false: 上传失败</return_state>
     * <return_msg>true: 返回文件上传到服务器的路径 false: 文件上传的失败信息反馈</return_msg>
     */
    public static Map<String,Object> UploadLimitSizeOSS(MultipartFile file, String bucketName, String diskName, int limitSize){
        if (file == null) {
            resultMap.put("state", false);
            resultMap.put("msg", "未选择文件!");
            return resultMap;
        }
        // 把单位M转换为bytes
        long limitSizeBytes = limitSize * 1024 * 1024;
        if (file.getSize() > limitSizeBytes) {
            resultMap.put("state", false);
            resultMap.put("msg", "您上传的文件超出限制大小" + limitSize + "M");
            return resultMap;
        }
        return uploadFileOSS(file,bucketName,diskName);

    }

    /**
     * 上传图片到到OSS服务器
     * <note>同名文件会覆盖原文件的内容后保存新的内容到服务器</note>
     * @param file 上传的文件
     * @param bucketName 上传空间名称
     * @param diskName 文件存放的位置标识
     * @param limitSize     上传大小
     * @return Map<String, Object> map
     * <return_state>true：上传成功  false: 上传失败</return_state>
     * <return_msg>true: 返回文件上传到服务器的路径 false: 文件上传的失败信息反馈</return_msg>
     */
    public Map<String, Object> ImgUploadLimitSizeOSS(MultipartFile file, String bucketName, String diskName, int limitSize) throws FileNotFoundException {
        if (file == null) {
            resultMap.put("state", false);
            resultMap.put("msg", "未选择文件!");
            return resultMap;
        }
        if (!ImageUtils.isImage(new File( file.getOriginalFilename()))) {
            resultMap.put("state", false);
            resultMap.put("msg", "请选择上传图片文件!");
            return resultMap;
        }
        // 把单位M转换为bytes
        long limitSizeBytes = limitSize * 1024 * 1024;
        if (file.getSize() > limitSizeBytes) {
            resultMap.put("state", false);
            resultMap.put("msg", "您上传的文件超出限制大小" + limitSize + "M");
            return resultMap;
        }

        return uploadFileOSS(file,bucketName,diskName);
    }


    /**
     * 根据key获取OSS服务器上的文件输入流
     * @param bucketName bucket名称
     * @param diskName 文件路径
     * @param key Bucket下的文件的路径名+文件名
     */
    public static final InputStream getOSS2InputStream( String bucketName, String diskName, String key){
        OSSObject ossObj = ossClient.getObject(bucketName, diskName + key);
        return ossObj.getObjectContent();
    }

    /**
     * 根据key删除OSS服务器上的文件
     * @param bucketName bucket名称
     * @param diskName 文件路径
     * @param key Bucket下的文件的路径名+文件名
     */
    public static void deleteFile(String bucketName, String diskName, String key){
        ossClient.deleteObject(bucketName, diskName + key);
        logger.info("删除" + bucketName + "下的文件" + diskName + key + "成功");
    }

    /**
     * 获取资源的URL
     * @param key 资源key值
     * @param bucketName bucket名称
     * @return
     */
    public static String getUrl(String key,String bucketName) {
        // 设置URL过期时间为10年 3600l* 1000*24*365*10
        Date expiration = new Date(System.currentTimeMillis() + 3600L * 1000 * 24 * 365 * 10);
        // 生成URL
        URL url = ossClient.generatePresignedUrl(bucketName, key, expiration);
        if (url != null) {
            return url.toString();
        }
        return null;
    }
}
